//
//  RecordViewController.swift
//  VoiceMemos
//
//  Created by Zhouqi Mo on 2/24/15.
//  Copyright (c) 2015 Zhouqi Mo. All rights reserved.
// https://github.com/SwiftStudioIst/VoiceMemos

import UIKit
import AVFoundation

class RecordViewController: BaseViewController {

    // MARK: Property

    var audioRecorder: AVAudioRecorder?
    var meterTimer: Timer?
    var recordDuration: TimeInterval = 10 // 10 * 60.0 //录制时长120s, 2分钟
    var contentView = UIView()
    var durationLabel: UILabel = labelView()
    var tipLabel: PaddingLabel = paddingLabel()
    var voiceRecordHUD: KMVoiceRecordHUD = KMVoiceRecordHUD()

    // MARK: View Life Cycle

    override func viewDidLoad() {
        super.viewDidLoad()

        view.backgroundColor = .clear

        view.render(contentView) {
            $0.backgroundColor = "#80000000".toColor()
            $0.setRadius(Res.size.roundNormal)
            $0.makeCenter()
            $0.makeWidthHeight(160, 170)
        }
        contentView.render(durationLabel) {
            $0.setTextColor(Res.color.white)
            $0.makeGravityTop()
            $0.makeCenterX()
            $0.makeHeight(30)
        }
        contentView.render(voiceRecordHUD) {
            $0.makeTopToBottomOf(self.durationLabel)
            $0.makeGravityBottom(priority: .medium)
            $0.makeCenterX()
            $0.makeWidth(100)
            $0.makeHeight(100)
        }
        contentView.render(tipLabel) {
            $0.setTextColor(Res.color.white)
            $0.text = "上滑取消录制"
            $0.setRadius(Res.size.roundMin)
            $0.makeTopToBottomOf(self.voiceRecordHUD, offset: Res.size.l)
            $0.makeCenterX()
        }
        voiceRecordHUD.update(0.0)
        durationLabel.text = ""
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        NotificationCenter.default.removeObserver(self, name: AVAudioSession.interruptionNotification, object: AVAudioSession.sharedInstance())
    }

    // MARK: Target Action

    /// 录制完成回调
    var onRecordFinish: ((_ url: URL?, _ cancel: Bool) -> Void)? = nil

    /// 完成录制
    func finishRecord(_ sender: AnyObject? = nil, cancel: Bool = false) {
        meterTimer?.invalidate()
        meterTimer = nil
        voiceRecordHUD.update(0.0)
        if let audioRecorder = audioRecorder, audioRecorder.currentTime ?? 0 > 0, !cancel {
            audioRecorder.stop()
            //performSegueWithIdentifier("Update Recording", sender: self)
            onRecordFinish?(audioRecorder.url, false)
        } else {
            audioRecorder = nil
            //performSegueWithIdentifier("Cancel Recording", sender: self)
            onRecordFinish?(nil, true)
        }
        AudioSessionHelper.setupSessionActive(false)
        hide(self)
    }

    // MARK: Notification

    @objc func handleInterruption(notification: NSNotification) {
        if let userInfo = notification.userInfo {
            let interruptionType = userInfo[AVAudioSessionInterruptionTypeKey] as! UInt
            if interruptionType == AVAudioSession.InterruptionType.began.rawValue {
                if audioRecorder?.isRecording == true {
                    audioRecorder?.pause()
                }
                meterTimer?.invalidate()
                meterTimer = nil
                voiceRecordHUD.update(0.0)
            } else if interruptionType == AVAudioSession.InterruptionType.ended.rawValue {
                let alertController = UIAlertController(title: nil, message: "Do you want to continue the recording?", preferredStyle: .alert)

                let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { _ in
                    self.finishRecord(self)
                }
                alertController.addAction(cancelAction)

                let resumeAction = UIAlertAction(title: "Resume", style: .default) { _ in
                    self.delay(0.8) {
                        if let recorder = self.audioRecorder {
                            recorder.record()
                            self.updateRecorderCurrentTimeAndMeters()
                            self.meterTimer = Timer.scheduledTimer(timeInterval: 0.1,
                                    target: self,
                                    selector: #selector(self.updateRecorderCurrentTimeAndMeters),
                                    userInfo: nil,
                                    repeats: true)
                            //self.meterTimer?.fire()
                        }
                    }
                }
                alertController.addAction(resumeAction)

                present(alertController, animated: true, completion: nil)
            }
        }
    }

    // MARK: Other

    func delay(_ time: TimeInterval, block: @escaping () -> Void) {
        doMain(time, action: block)
    }

    @objc func updateRecorderCurrentTimeAndMeters() {
        if let recorder = audioRecorder {
            let currentTime = Int(recorder.currentTime)
            let timeLeft = Int(recordDuration) - currentTime
            if timeLeft > 10 {
                durationLabel.text = "\(currentTime)″"
            } else {
                //voiceRecordHUD.fillColor = UIColor.red
                durationLabel.text = "\(timeLeft)″" //"\(timeLeft) seconds left"
                if timeLeft == 0 {
                    //durationLabel.text = "Time is up"
                    finishRecord(self)
                }
            }

            if recorder.isRecording {
                recorder.updateMeters()
                let ALPHA = 0.05
                let peakPower = pow(10, (ALPHA * Double(recorder.peakPower(forChannel: 0))))
                var rate: Double = 0.0
                if (peakPower <= 0.2) {
                    rate = 0.2
                } else if (peakPower > 0.9) {
                    rate = 1.0
                } else {
                    rate = peakPower
                }
                voiceRecordHUD.update(CGFloat(rate))
            }
        }
    }

    /// 开始录制
    @discardableResult
    func configRecorderWithURL(url: URL? = nil) -> URL {
        let path = Path.userCaches + "/record"
        let url = url ?? timeFileName(suffix: ".wav").createFileURL(path: path.standardRawValue)
        configRecorderWithURL(url: url, delegate: self)
        return url
    }

    func configRecorderWithURL(url: URL, delegate: AVAudioRecorderDelegate) {
        let session: AVAudioSession = AVAudioSession.sharedInstance()

        session.requestRecordPermission { granted in
            if granted {
                debugPrint("Recording permission has been granted")
                let recordSettings: [String: Any] = [
                    AVFormatIDKey: NSNumber(value: kAudioFormatLinearPCM),
                    AVSampleRateKey: 44100.0,
                    AVNumberOfChannelsKey: 2,
                    AVLinearPCMBitDepthKey: 16,
                    AVLinearPCMIsBigEndianKey: false,
                    AVLinearPCMIsFloatKey: false,
                ]
                self.audioRecorder = try? AVAudioRecorder(url: url, settings: recordSettings)
                guard let recorder = self.audioRecorder else {
                    return
                }
                recorder.delegate = delegate
                recorder.isMeteringEnabled = true
                AudioSessionHelper.postStartAudioNotification(recorder)
                self.delay(0.8) {
                    AudioSessionHelper.setupSessionActive(true, category: .record)
                    if recorder.prepareToRecord() {
                        recorder.record(forDuration: self.recordDuration)
                        L.i("开始录制:\(url.path)")

                        NotificationCenter.default.addObserver(self, selector: #selector(self.handleInterruption(notification:)), name: AVAudioSession.interruptionNotification, object: AVAudioSession.sharedInstance())

                        self.updateRecorderCurrentTimeAndMeters()
                        self.meterTimer = Timer.scheduledTimer(timeInterval: 0.1,
                                target: self,
                                selector: #selector(self.updateRecorderCurrentTimeAndMeters),
                                userInfo: nil,
                                repeats: true)
                        //self.meterTimer?.fire()
                    }
                }
            } else {
                debugPrint("Recording permission has been denied")
            }
        }
    }
}

//MARK: AVAudioRecorderDelegate

extension RecordViewController: AVAudioRecorderDelegate {

    public func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) {
        L.i("录制结束:\(flag):\(recorder.url)")
    }

    public func audioRecorderEncodeErrorDidOccur(_ recorder: AVAudioRecorder, error: Error?) {
        L.e("录制异常:\(error)")
    }

    public func audioRecorderBeginInterruption(_ recorder: AVAudioRecorder) {
        L.w("录制被中断:\(recorder)")
    }

    public func audioRecorderEndInterruption(_ recorder: AVAudioRecorder, withOptions flags: Int) {
        L.w("录制恢复:\(flags):\(recorder)")
    }
}
